/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package at.irian.demo.jsfatwork.domain;

import at.irian.demo.jsfatwork.application.validation.Before;
import static at.irian.demo.jsfatwork.domain.DomainQueryDetails.*;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author Gerhard Petracek
 */
@Entity
@Table(name = "T_Poll")
@NamedQuery(name = FIND_OPEN_POLLS,
        query = "select p from Poll p where " +
                "p.active = true and " +
                C_PARAMETER_CURRENT_DATE + " between p.startDate and p.endDate and " +
                "p.group in(select g from Group g join g.users u where u = " + C_PARAMETER_USER + ")"
)
public class Poll extends AbstractDomainObject
{
    private static final long serialVersionUID = -3821308345433991346L;

    public Poll()
    {
    }

    public Poll(boolean active, Date startDate, Date endDate)
    {
        this.active = active;
        this.startDate = startDate;
        this.endDate = endDate;
    }

    @Column(nullable = false, length = 32, unique = true)
    private String topic;

    @Column(length = 128)
    private String description;

    @Before(valueOf = "endDate")
    @Temporal(TemporalType.DATE)
    @Column(nullable = false)
    private Date startDate;

    @Temporal(TemporalType.DATE)
    @Column(nullable = false)
    private Date endDate;

    @Column(nullable = false)
    private boolean active;

    @Column
    private boolean multipleAnswerMode;

    public void addVote(Vote vote)
    {
        this.votes.add(vote);
    }

    public void addAnswer(Answer answer)
    {
        this.answers.add(answer);
        answer.setPoll(this);
    }

    @Basic(optional = true)
    @OneToMany(mappedBy = "poll", fetch = FetchType.EAGER)
    private List<Vote> votes = new ArrayList<Vote>();

    @ManyToOne(optional = false)
    private User owner;

    @ManyToOne(optional = false)
    private Group group;

    @Basic(optional = false)
    @OneToMany(mappedBy = "poll", cascade = CascadeType.ALL)
    private List<Answer> answers = new ArrayList<Answer>();

    public boolean isActive()
    {
        return active && isOngoing();
    }

    private boolean isOngoing()
    {
        if(isTransient())
        {
            return true;
        }

        Date now = new Date();
        return now.after(this.startDate) && now.before(this.endDate);
    }

    /*
     * generated
     */

    //common/possible performance pitfall in combination with lazy loading
    public List<Vote> getVotes()
    {
        return votes;
    }

    public User getOwner()
    {
        return owner;
    }

    public void setOwner(User owner)
    {
        this.owner = owner;
    }

    public List<Answer> getAnswers()
    {
        return answers;
    }

    public String getTopic()
    {
        return topic;
    }

    public void setTopic(String topic)
    {
        this.topic = topic;
    }

    public String getDescription()
    {
        return description;
    }

    public void setDescription(String description)
    {
        this.description = description;
    }

    public Date getStartDate()
    {
        return startDate;
    }

    public void setStartDate(Date startDate)
    {
        this.startDate = startDate;
    }

    public Date getEndDate()
    {
        return endDate;
    }

    public void setEndDate(Date endDate)
    {
        this.endDate = endDate;
    }

    public void setActive(boolean active)
    {
        this.active = active;
    }

    public Group getGroup()
    {
        return group;
    }

    public void setGroup(Group group)
    {
        this.group = group;
    }

    public boolean isMultipleAnswerMode()
    {
        return multipleAnswerMode;
    }

    public void setMultipleAnswerMode(boolean multipleAnswerMode)
    {
        this.multipleAnswerMode = multipleAnswerMode;
    }
}
